home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’89 / gadlife / source (ugly) / patch.drag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-10  |  14.3 KB  |  513 lines  |  [TEXT/KAHL]

  1. #include "main.h"
  2. #include "patch.h"
  3.  
  4. Pattern            dragPat;
  5.  
  6. static WindowPeek    messyLevel;
  7. static long            oldDragWindow, oldGrowWindow;
  8.  
  9. /*******************************************************
  10. *                                                                *
  11. *                                                                *
  12. *******************************************************/
  13.  
  14. defineSizeRgn( theRgn, theRect )
  15.     Rect            *theRect;
  16.     RgnHandle        theRgn;
  17.     {
  18.     Rect            bounds, temp;
  19.     
  20.     OpenRgn();
  21.     bounds = *theRect;
  22.     SetRect( &temp, bounds.left, bounds.top - 1, bounds.right, bounds.top );
  23.     FrameRect( &temp );
  24.     temp.top -= 18;
  25.     temp.bottom -= 18;
  26.     FrameRect( &temp );
  27.     temp.top = bounds.bottom;
  28.     temp.bottom = bounds.bottom + 1;
  29.     FrameRect( &temp );
  30.     temp.top -= 15;
  31.     temp.bottom -= 15;
  32.     FrameRect( &temp );
  33.     SetRect( &temp, bounds.left - 1, bounds.top - 19, bounds.left, bounds.bottom + 1 );
  34.     FrameRect( &temp );
  35.     temp.left = bounds.right;
  36.     temp.right = bounds.right + 1;
  37.     FrameRect( &temp );
  38.     SetRect( &temp, bounds.right - 15, bounds.top, bounds.right - 14, bounds.bottom );
  39.     FrameRect( &temp );
  40.     CloseRgn( theRgn );
  41.     }
  42.  
  43. /*******************************************************
  44. *                                                                *
  45. *    This is real ugly, but it's also real fast.  It assumes the structure of the size    *
  46. *    region and updates those values that need updating.                        *
  47. *                                                                *
  48. *******************************************************/
  49.  
  50. deltaSizeRgn( theRgn, dh, dv )
  51.     RgnHandle    theRgn;
  52.     int        dh, dv;
  53.     {
  54.     int        *data;
  55.     
  56.     HLock( theRgn );
  57.     data = *(int**)theRgn;
  58.     data[3] = data[37] = 1 + ( data[31] += dv );                /* d', d    */
  59.     data[20] = data[34] = 1 + ( data[19] = data[33] += dh );        /* 4, 3    */
  60.     data[27] = 1 + ( data[23] += dv );                        /* c', c    */
  61.     data[4] = data[7] = data[39] =                             /* 6, 5    */
  62.         1 + ( data[11] = data[15] = data[21] = data[25] = data[29] = data[35] += dh );
  63.     }
  64.  
  65. /*******************************************************
  66. *                                                                *
  67. *    This routine passes the appropriate parameters to the WDEF assocaited with    *
  68. *    theWindow, and returns the result code.  This is only here as there was some    *
  69. *    difficultly casting a long to a pointer to a pascal function returning a long.        *
  70. *    It gets used when there is a click in a DA window to discover if the click was    *
  71. *    in the close box or in the drag region, so we can trap these.                *
  72. *                                                                *
  73. *******************************************************/
  74.  
  75. long wDefCall( defProc, varCode, theWindow, message, param )
  76.     long    defProc, theWindow;
  77.     Rect    *param;
  78.     int    varCode, message;
  79.     {
  80.     long    result = 0;
  81.     
  82.     asm    {
  83.         subq.l    #4,sp
  84.         move    varCode,-(sp)
  85.         move.l    theWindow,-(sp)
  86.         move    message,-(sp)
  87.         move.l    param,-(sp)
  88.         move.l    defProc, a0
  89.         move.l    (a0),a0
  90.         jsr        (a0)
  91.         move.l    (sp)+,result
  92.         }
  93.     return( result );
  94.     }
  95.  
  96. /*******************************************************
  97. *                                                                *
  98. *    This is here mostly because of type checking problems with the compiler.        *
  99. *                                                                *
  100. *******************************************************/
  101.  
  102. myPinRect( theRect, thePt )
  103.     Rect    *theRect;
  104.     Point    *thePt;
  105.     {
  106.     if( thePt->h >= theRect->right )        thePt->h = theRect->right - 1;
  107.     if( thePt->h < theRect->left )        thePt->h = theRect->left;
  108.     if( thePt->v >= theRect->bottom )    thePt->v = theRect->bottom - 1;
  109.     if( thePt->v < theRect->top )        thePt->v = theRect->top;
  110.     }
  111.  
  112. /*******************************************************
  113. *                                                                *
  114. *    This emulates the DragGrayRgn routine, but does things a little differently.    *
  115. *    Instead of modifying the original region, it leaves it alone and works with a    *
  116. *    copy.  It assumes that slopRect = pinRect, and assumes that there is no axis    *
  117. *    restriction.  It calls actionProc with the current GrayRgn, so it knows where    *
  118. *    to mask out if it is drawing to the screen.                                *
  119. *                                                                *
  120. *******************************************************/
  121.  
  122. setDragPat( thePat )
  123.     Pattern    *thePat;
  124.     {
  125.     *(long*)dragPat = *(long*)thePat;
  126.     ((long*)dragPat)[1] = ((long*)thePat)[1];
  127.     }
  128.  
  129. long doDragTheRgn( startRgn, startPt, limitRect, slopRect, axis )
  130.     RgnHandle        startRgn;
  131.     Point            startPt;
  132.     Rect            *limitRect, *slopRect;
  133.     int            axis;
  134.     {
  135.     RgnHandle        theRgn, oldRgn, deltaRgn, slopRgn;
  136.     Point            currPt, lastPt, pinPt;
  137.     EventRecord    theEvent;
  138.     int            offh = 0, offv = 0, outside = 0, oldOutside = 0, doPin;
  139.     PenState        savePen;
  140.     
  141.     slopRgn = NewRgn();
  142.     CopyRgn( GrayRgn, slopRgn );
  143.     InsetRgn( slopRgn, 4, 4 );
  144.     doPin = 0;                /* for now.  Should actually check to make sure it is on full screen and near edges    */
  145.     
  146.     GetPenState( &savePen );
  147.     PenMode( notPatXor );
  148.     PenPat( dragPat );
  149.     theRgn = NewRgn();
  150.     deltaRgn = NewRgn();
  151.     oldRgn = NewRgn();
  152.     CopyRgn( startRgn, theRgn );
  153.     InsetRgn( theRgn, 1, 1 );
  154.     DiffRgn( startRgn, theRgn, theRgn );
  155.     CopyRgn( theRgn, oldRgn );
  156.     PaintRgn( theRgn );
  157.     lastPt = startPt;
  158.     while( StillDown() )
  159.         {
  160.         GetMouse( &currPt );
  161.         if( axis == hAxisOnly ) currPt.v = lastPt.v;
  162.         else if( axis == vAxisOnly ) currPt.h = lastPt.h;
  163.         pinPt = currPt;
  164.         if( doPin && limitRect ) myPinRect( limitRect, &pinPt );
  165.         if( !EqualPt( currPt, lastPt ))
  166.             {
  167.             OffsetRgn( oldRgn, offh, offv );
  168.             OffsetRgn( theRgn, offh = pinPt.h - lastPt.h, offv = pinPt.v - lastPt.v );
  169.             outside = !PtInRgn( currPt, slopRgn );
  170.             if( !( outside && oldOutside ))
  171.                 {
  172.                 if( outside ) CopyRgn( oldRgn, deltaRgn );
  173.                 else    if( oldOutside ) CopyRgn( theRgn, deltaRgn );
  174.                     else    XorRgn( theRgn, oldRgn, deltaRgn );
  175.                 PaintRgn( deltaRgn );
  176.                 oldOutside = outside;
  177.                 }
  178.             lastPt = currPt;
  179.             }
  180.         doBackground( lotsElseToDo, outside ? noGray : someGray, theRgn );
  181.         }
  182.     GetMouse( &currPt );
  183.     if( !outside ) PaintRgn( theRgn );
  184.     DisposeRgn( theRgn );
  185.     DisposeRgn( oldRgn );
  186.     DisposeRgn( deltaRgn );
  187.     SetPenState( &savePen );
  188.     
  189.     if( PtInRgn( currPt, slopRgn ))
  190.         SubPt( startPt, &currPt );
  191.     else    currPt.v = currPt.h = -32768;
  192.     DisposeRgn( slopRgn );
  193.     return( *(long*)&(currPt.v) );
  194.     }
  195.  
  196. /*******************************************************
  197. *                                                                *
  198. *                                                                *
  199. *******************************************************/
  200.  
  201. long doGrowWindow( theWindow, startPt, bounds )
  202.     WindowPeek    theWindow;
  203.     Point            startPt;
  204.     Rect            *bounds;
  205.     {
  206.     EventRecord    theEvent;
  207.     GrafPtr        bigPort, savePort;
  208.     PenState        savePen;
  209.     RgnHandle        saveClip, theRgn, oldRgn, deltaRgn;
  210.     Rect            sizeRect, theRect;
  211.     Point            upperLeft, currPt, lastPt, theSize, oldSize;
  212.     long            defProc, result;
  213.     int            varCode, dh, dv, oldh, oldv, offh, offv;
  214.     
  215.     defProc = (long)(theWindow->windowDefProc);
  216.     varCode = ( defProc >> 24 ) & 0xf;
  217.     defProc &= 0xffffff;
  218.     
  219.     GetWMgrPort( &bigPort );
  220.     GetPort( &savePort );
  221.     SetPort( bigPort );
  222.     saveClip = NewRgn();
  223.     GetClip( saveClip );
  224.     SetClip( GrayRgn );
  225.     GetPenState( &savePen );
  226.     PenMode( notPatXor );
  227.     setDragPat( gray );
  228.     PenPat( gray );
  229.     
  230.     upperLeft = topLeft( theWindow->port.portBits.bounds );
  231.     sizeRect = theWindow->port.portRect;
  232.     OffsetRect( &sizeRect, -upperLeft.h, -upperLeft.v );
  233.     lastPt = startPt;
  234.     theRect = *bounds;
  235.     OffsetRect( &theRect,     sizeRect.left + startPt.h - sizeRect.right, 
  236.                         sizeRect.top + startPt.v - sizeRect.bottom );
  237.     if( theRect.right < 0 ) theRect.right = 32767;
  238.     if( theRect.bottom < 0 ) theRect.bottom = 32767;
  239.     theRgn = NewRgn();
  240.     oldRgn = NewRgn();
  241.     deltaRgn = NewRgn();
  242.     defineSizeRgn( theRgn, &sizeRect );
  243.     CopyRgn( theRgn, oldRgn );
  244.     oldh = oldv = 0;
  245.     PaintRgn( theRgn );
  246.     while( StillDown() )
  247.         {
  248.         GetMouse( &currPt );
  249.         myPinRect( &theRect, &currPt );
  250.         dh = currPt.h - lastPt.h;
  251.         dv = currPt.v - lastPt.v;
  252.         if( dv || dh )
  253.             {
  254.             sizeRect.right += dh;
  255.             sizeRect.bottom += dv;
  256.             deltaSizeRgn( oldRgn, oldh, oldv );
  257.             deltaSizeRgn( theRgn, dh, dv );
  258.             XorRgn( theRgn, oldRgn, deltaRgn );
  259.             PaintRgn( deltaRgn );
  260.             oldh = dh;
  261.             oldv = dv;
  262.             lastPt = currPt;
  263.             }
  264.         doBackground( lotsElseToDo, allGray, theRgn );
  265.         }
  266.     GetMouse( &currPt );
  267.     PaintRgn( theRgn );
  268.     DisposeRgn( theRgn );
  269.     DisposeRgn( oldRgn );
  270.     DisposeRgn( deltaRgn );
  271.     SetPenState( &savePen );
  272.     
  273.     myPinRect( &theRect, &currPt );
  274.     theSize.h = sizeRect.right + currPt.h - lastPt.h - sizeRect.left;
  275.     theSize.v = sizeRect.bottom + currPt.v - lastPt.v - sizeRect.top;
  276.     oldSize = botRight( theWindow->port.portRect );
  277.     SubPt( topLeft( theWindow->port.portRect ), &oldSize );
  278.     if( !EqualPt( oldSize, theSize )) result = *(long*)&theSize;
  279.     else    result = 0;
  280.     
  281.     SetClip( saveClip );
  282.     DisposeRgn( saveClip );
  283.     SetPort( savePort );
  284.     return( result );
  285.     }
  286.  
  287. /*******************************************************
  288. *                                                                *
  289. *    This emulates the DragWindow routine, by calling DragGrayRgn with a copy    *
  290. *    of the strucRgn of the given window.  It also passes a backgrounding routine    *
  291. *    as the actionProc.  This is used instead of the DragHook global because when    *
  292. *    that was tried, it crashed.                                            *
  293. *                                                                *
  294. *******************************************************/
  295.  
  296. long doDragWindowPart( theWindow, where, bounds, front )
  297.     WindowPeek    theWindow;
  298.     Point            where;
  299.     Rect            *bounds;
  300.     int            front;
  301.     {
  302.     GrafPtr        bigPort, savePort;
  303.     RgnHandle        saveClip;
  304.     long            offsets;
  305.     
  306.     GetWMgrPort( &bigPort );
  307.     GetPort( &savePort );
  308.     SetPort( bigPort );
  309.     saveClip = NewRgn();
  310.     GetClip( saveClip );
  311.     SetClip( GrayRgn );
  312.     if( !front ) ClipAbove( theWindow );
  313.     messyLevel = front ? NULL : theWindow;
  314.     setDragPat( gray );
  315.     offsets = doDragTheRgn( theWindow->strucRgn, where, bounds, bounds, noConstraint );
  316.     SetClip( saveClip );
  317.     DisposeRgn( saveClip );
  318.     SetPort( savePort );
  319.     return( offsets );
  320.     }
  321.  
  322. doDragWindow( theWindow, where, bounds )
  323.     WindowPeek    theWindow;
  324.     Point            where;
  325.     Rect            *bounds;
  326.     {
  327.     PixMapPtr    thePixMap;
  328.     long            offsets;
  329.     int            dv, dh, oldv, oldh, bitsLeft, bitsTop, front;
  330.     
  331.     if( theWindow->port.portBits.rowBytes & 0xc000 )
  332.         {
  333.         thePixMap = *(((CGrafPtr)theWindow)->portPixMap);
  334.         bitsLeft = thePixMap->bounds.left;
  335.         bitsTop = thePixMap->bounds.top;
  336.         }
  337.     else    {
  338.         bitsLeft = theWindow->port.portBits.bounds.left;
  339.         bitsTop = theWindow->port.portBits.bounds.top;
  340.         }
  341.     front = !( getModifiers() & cmdKey );
  342.     offsets = doDragWindowPart( theWindow, where, bounds, front );
  343.     dv = HiWord( offsets );
  344.     dh = LoWord( offsets );
  345.     if(( dv != -32768 || dh != -32768 ) && ( dv != 0 || dh != 0 ))
  346.         {
  347.         oldh = theWindow->port.portRect.left - bitsLeft;
  348.         oldv = theWindow->port.portRect.top - bitsTop;
  349.         MoveWindow( theWindow, dh + oldh, dv + oldv, front );
  350.         }
  351.     else if( front ) SelectWindow( theWindow );
  352.     }
  353.  
  354. /*******************************************************
  355. *                                                                *
  356. *    CleanWindow returns true if the given window is in front of messyLevel.  This    *
  357. *    is used when the gray on the screen is from a partially-obscured drag, to        *
  358. *    detect whether there might be gray drawn on the contents of the window.        *
  359. *                                                                *
  360. *******************************************************/
  361.  
  362. int cleanWindow( theWindow )
  363.     WindowPeek    theWindow;
  364.     {
  365.     if( theWindow == messyLevel || !messyLevel ) return( 0 );
  366.     while( theWindow = theWindow->nextWindow )
  367.         if( theWindow == messyLevel ) return( -1 );
  368.     return( 0 );
  369.     }
  370.  
  371. /*******************************************************
  372. *                                                                *
  373. *    This is just for now - it should be easy to write one that calls the wDefProc    *
  374. *    directly and does its stuff…                                        *
  375. *                                                                *
  376. *******************************************************/
  377.  
  378. int doTrackGoAway( theWindow, where )
  379.     WindowPtr    theWindow;
  380.     Point            where;
  381.     {
  382.     int    result;
  383.     
  384.     installWaitTrap();
  385.     result = TrackGoAway( theWindow, where );
  386.     removeWaitTrap();
  387.     return( result );
  388.     }
  389.     
  390. /*******************************************************
  391. *                                                                *
  392. *    The trap patching stuff for dragWindow, used by SystemClick in case there    *
  393. *    is a dragWindow done from a content-click.  (The alarm clock does this.)        *
  394. *                                                                *
  395. *******************************************************/
  396.  
  397. pascal doDragTrap( theWindow, startPt, boundsRect )
  398.     WindowPtr    theWindow;
  399.     Point            startPt;
  400.     Rect            *boundsRect;
  401.     {
  402.     asm    {
  403.         movem.l    d0-d7/a1-a5,-(sp)
  404.         move.l    CurrentA5,a5
  405.         }
  406.     removeWaitTrap();
  407.     doDragWindow( theWindow, startPt, boundsRect );
  408.     asm    {
  409.         movem.l    (sp)+,d0-d7/a1-a5
  410.         }
  411.     }
  412.  
  413. installDragWindowTrap()
  414.     {
  415.     oldDragWindow = NGetTrapAddress( DragWTrapNum, ToolTrap );
  416.     NSetTrapAddress( doDragTrap, DragWTrapNum, ToolTrap );
  417.     }
  418.     
  419. removeDragWindowTrap()
  420.     {
  421.     NSetTrapAddress( oldDragWindow, DragWTrapNum, ToolTrap );
  422.     }
  423.     
  424. /*******************************************************
  425. *                                                                *
  426. *    The trap patching stuff for growWindow, used by SystemClick stuff.            *
  427. *                                                                *
  428. *******************************************************/
  429.  
  430. pascal long doGrowTrap( theWindow, startPt, sizeRect )
  431.     WindowPtr    theWindow;
  432.     Point            startPt;
  433.     Rect            *sizeRect;
  434.     {
  435.     long            result;
  436.     
  437.     asm    {
  438.         movem.l    d0-d7/a1-a5,-(sp)
  439.         move.l    CurrentA5,a5
  440.         }
  441.     result = doGrowWindow( theWindow, startPt, sizeRect );
  442.     asm    {
  443.         movem.l    (sp)+,d0-d7/a1-a5
  444.         }
  445.     return( result );
  446.     }
  447.  
  448. installGrowTrap()
  449.     {
  450.     oldGrowWindow = NGetTrapAddress( GrowWTrapNum, ToolTrap );
  451.     NSetTrapAddress( doGrowTrap, GrowWTrapNum, ToolTrap );
  452.     }
  453.     
  454. removeGrowTrap()
  455.     {
  456.     NSetTrapAddress( oldGrowWindow, GrowWTrapNum, ToolTrap );
  457.     }
  458.     
  459. /*******************************************************
  460. *                                                                *
  461. *    This grabs some stuff before passing it along so that very little will block.        *
  462. *    Drag and GoAway are completely caught, and never passed to SystemClick.    *
  463. *    Size is special - the DA may need to adjust stuff, so I drag the size thing,         *
  464. *    without taking the mouseup event off the queue, and then call with the original    *
  465. *    mouse click point.  In all other cases it is just passed directly.  I tried to grab    *
  466. *    Zoom stuff, but it didn't work real well…                                *
  467. *                                                                *
  468. *******************************************************/
  469.  
  470. doSysWindow( theEvent, theWindow )
  471.     EventRecord    *theEvent;
  472.     WindowPeek    theWindow;
  473.     {
  474.     long            defProc, result;
  475.     int            varCode, gone;
  476.     
  477.     defProc = (long)(theWindow->windowDefProc);
  478.     varCode = ( defProc >> 24 ) & 0xf;
  479.     defProc &= 0xffffff;
  480.     result = wDefCall( defProc, varCode, theWindow, wHit, theEvent->where );
  481.     switch( result )
  482.         {
  483.         case    wInDrag:
  484.             doDragWindow( theWindow, theEvent->where, NULL );
  485.             break;
  486.         case wInGoAway:
  487.             if( doTrackGoAway( theWindow, theEvent->where ))
  488.                 doClose( theWindow );
  489.             break;
  490.         case wInGrow:
  491.             installGrowTrap();
  492.             SystemClick( theEvent, theWindow );
  493.             removeGrowTrap();
  494.             break;
  495.         default:
  496.             installDelayTrap();
  497.             installSndPatch();
  498.             installPopUpTrap();
  499.             installDragWindowTrap();
  500.             installModalTrap();
  501.             installWaitTrap();
  502.             installAvailTrap();            /* miniDraw uses EventAvail on drawing instead of WaitMouseUp */
  503.             SystemClick( theEvent, theWindow );
  504.             removeAvailTrap();
  505.             removeWaitTrap();
  506.             removeModalTrap();
  507.             removeDragWindowTrap();
  508.             removePopUpTrap();
  509.             removeSndPatch();
  510.             removeDelayTrap();
  511.         }
  512.     }
  513.